﻿Ext.util.HashMap = Ext.extend(Ext.util.Observable, {
    constructor: function (config) {
        this.addEvents(

            'add',

            'clear',

            'remove',

            'replace'
        );

        Ext.util.HashMap.superclass.constructor.call(this, config);

        this.clear(true);
    },

    //获取哈希元素数量。
    getCount: function () {
        return this.length;
    },

    //返回一个代表[key, value]键值对的数组，如果没有传入value，则相当于：[key.id, key]
    getData: function (key, value) {

        if (value === undefined) {
            value = key;
            key = this.getKey(value);
        }

        return [key, value];
    },

    //返回参数的id
    getKey: function (o) {
        return o.id;
    },

    //增加一个键值对
    add: function (key, value) {
        var me = this,
            data;

        if (me.containsKey(key)) {//存在以key的值作为名称的属性
            throw new Error('This key already exists in the HashMap');
        }

        data = this.getData(key, value);//返回一个[key, value]数组
        key = data[0];
        value = data[1];
        me.map[key] = value;//给map对象增加一个属性，属性名为key值，属性值为value值
        ++me.length;//元素数量加1
        me.fireEvent('add', me, key, value); //触发指定的事件,并在这里把处理函数的参数传入（应该至少要有事件的名称）。
        return value;
    },

    //替换hash中的一个元素。如果该键不存在，add方法将被使用。
    replace: function (key, value) {
        var me = this,
            map = me.map,
            old;

        if (!me.containsKey(key)) {//如果key不存在，则添加键值对
            me.add(key, value);
        }
        old = map[key];
        map[key] = value;
        me.fireEvent('replace', me, key, value, old);
        return value;
    },

    //从哈希表中移除一个元素，参数代表元素的值，成功返回true，失败返回false
    remove: function (o) {
        var key = this.findKey(o);
        if (key !== undefined) {
            return this.removeByKey(key);
        }
        return false;
    },

    //从哈希表中移除一个元素，参数代表元素的键，成功返回true，失败返回false
    removeByKey: function (key) {
        var me = this,
            value;

        if (me.containsKey(key)) {//如果该键存在
            value = me.map[key];
            delete me.map[key];
            --me.length;
            me.fireEvent('remove', me, key, value);
            return true;
        }
        return false;
    },

    //根据键取值
    get: function (key) {
        return this.map[key];
    },

    //清除哈希表中所有元素
    clear: function (initial) {
        var me = this;
        me.map = {};
        me.length = 0;
        if (initial !== true) {
            me.fireEvent('clear', me);
        }
        return me;
    },

    //如果this.map中以key的值做为名称的属性存在，则返回true，否则返回false
    containsKey: function (key) {
        return this.map[key] !== undefined;
    },

    //判断哈希表中是否有value值
    contains: function (value) {
        return this.containsKey(this.findKey(value));
    },

    //返回所有的键，类型为数组
    getKeys: function () {
        return this.getArray(true);
    },

    //返回所有的值，类型为数组
    getValues: function () {
        return this.getArray(false);
    },

    //获取所有元素的键或值，参数为true时返回所有的键，参数为false时返回所有的值
    getArray: function (isKey) {
        var arr = [],
            key,
            map = this.map;
        for (key in map) {
            if (map.hasOwnProperty(key)) {
                arr.push(isKey ? key : map[key]);
            }
        }
        return arr;
    },

    //遍历哈希表，每遍历到一个元素就执行一次fn函数，scope是函数运行的作用域，默认为this
    each: function (fn, scope) {

        var items = Ext.apply({}, this.map),
            key,
            length = this.length;

        scope = scope || this;
        for (key in items) {
            if (items.hasOwnProperty(key)) {
                if (fn.call(scope, key, items[key], length) === false) {//如果函数返回false则跳出
                    break;
                }
            }
        }
        return this;
    },

    //执行这个哈希的浅表副本。
    clone: function () {
        var hash = new Ext.util.HashMap(),
            map = this.map,
            key;

        hash.suspendEvents(); //暂停触发的所有事件。
        for (key in map) {
            if (map.hasOwnProperty(key)) {
                hash.add(key, map[key]);
            }
        }
        hash.resumeEvents();//恢复触发的事件
        return hash;
    },

    //根据value值查询key值
    findKey: function (value) {
        var key,
            map = this.map;

        for (key in map) {
            if (map.hasOwnProperty(key) && map[key] === value) {
                return key;
            }
        }
        return undefined;
    }
});